package co.edu.udea.herbario.logneg.imp;

import java.util.Date;
import java.util.GregorianCalendar;
import co.edu.udea.herbario.dao.AdministradorDao;
import co.edu.udea.herbario.dao.EjemplarDao;
import co.edu.udea.herbario.dao.EspecieDao;
import co.edu.udea.herbario.dao.MunicipioDao;
import co.edu.udea.herbario.dto.Administrador;
import co.edu.udea.herbario.dto.Ejemplar;
import co.edu.udea.herbario.dto.Especie;
import co.edu.udea.herbario.dto.Municipio;
import co.edu.udea.herbario.excepcion.Excepcion;
import co.edu.udea.herbario.excepcion.ExcepcionLogicaNegocio;
import co.edu.udea.herbario.logneg.AdministracionEjemplares;

/**
 * Esta clase contiene la implementacion de los metodos planteados en la interface AdministracionEjemplaresImp
 * 
 * @author Alejandro Areiza, Marcela Colorado
 *
 */
public class AdministracionEjemplaresImp implements AdministracionEjemplares 
{
	EjemplarDao ejemplardao;	//instanciacion de objeto tipo EjemplarDao para la implementacion de funciones
	EspecieDao especiedao;	//instanciacion de objeto tipo EspecieDao para la implementacion de funciones
	MunicipioDao municipiodao;	//instanciacion de objeto tipo MunicipioDao para la implementacion de funciones
	AdministradorDao administradordao;	//instanciacion de objeto tipo AdministradorDao para la implementacion de funciones

	public EjemplarDao getEjemplardao() {
		return ejemplardao;
	}

	public void setEjemplardao(EjemplarDao ejemplardao) {
		this.ejemplardao = ejemplardao;
	}

	public EspecieDao getEspeciedao() {
		return especiedao;
	}

	public void setEspeciedao(EspecieDao especiedao) {
		this.especiedao = especiedao;
	}

	public MunicipioDao getMunicipiodao() {
		return municipiodao;
	}

	public void setMunicipiodao(MunicipioDao municipiodao) {
		this.municipiodao = municipiodao;
	}

	public AdministradorDao getAdministradordao() {
		return administradordao;
	}

	public void setAdministradordao(AdministradorDao administradordao) {
		this.administradordao = administradordao;
	}

	@Override
	public void modificarEjemplar(int cod, String especie, String municipio, String nombreAutor, Date fechaDet, String nombreDeterminador,
			String nomColectorPpal, int numColeccion, Date fechaColeccion, String nomComun, String nomCien, int elevacionMin, int elevacionMax, 
			int gradsLat, int minLat, int segLat, int gradsLon, int minLon, int segLon, boolean publicarCoor, String colFlor, String colFruto, 
			String formaIngreso, String nomInstitucion, boolean disponible) throws Excepcion, ExcepcionLogicaNegocio 
	{
		Ejemplar ejem = ejemplardao.obtener(cod);	//obtiene el ejemplar asociado al codigo ingresado
													//desde la tabla Ejemplar
		
		if(ejem != null)	//verifica si el ejemplar fue hallado en la tabla Ejemplar		
		{
//			//comprobacion de claves foraneas respecto a la existencia de los datos asociados al ejemplar
			
			Especie espec = especiedao.obtenerEspeciePorNombre(especie);	
			if(espec == null)
			{
				throw new ExcepcionLogicaNegocio("La especie especificada no existe");
			}
			else
			{
				ejem.setEspecie(espec);
			}
			
			Municipio mun = municipiodao.obtenerMunicipioPorNombre(municipio);	
			if(mun == null)
			{				
				throw new ExcepcionLogicaNegocio("El municipio especificado no existe");
			}
			else
			{
				ejem.setMunicipio(mun);
			}
		
			
			//valida si los parametros ingresados son no nulos y no vacios, en ese caso los asigna al ejemplar
			
			if(nombreAutor!=null && !"".equals(nombreAutor))	
				ejem.setNombreAutor(nombreAutor);
			
			//crea un objeto tipo GregorianCalendar con la fecha actual
			GregorianCalendar fechaActual = new GregorianCalendar();
			//crea un objeto tipo GregorianCalendar con la fecha de nacimiento asignada
			GregorianCalendar fechaDato = new GregorianCalendar();	
			
			//valida que la fecha de nacimiento sea menor o igual a la fecha actual
			fechaDato.setTime(fechaDet);
			if(fechaDet != null && (fechaActual.after(fechaDato) || fechaActual.compareTo(fechaDato)==0))	
				ejem.setFechaDeterminacion(fechaDet);
			
			if(nombreDeterminador!=null && !"".equals(nombreDeterminador))
				ejem.setNombreDeterminador(nombreDeterminador);
			
			if(nomColectorPpal!=null && !"".equals(nomColectorPpal))
				ejem.setNombreColectorPrincipal(nomColectorPpal);
			
			if(numColeccion > 0)
				ejem.setNumeroColeccion(numColeccion);
			
			//valida que la fecha de coleccion sea menor o igual a la fecha actual
			fechaDato.setTime(fechaColeccion);
			if(fechaColeccion != null && (fechaActual.after(fechaDato) || fechaActual.compareTo(fechaDato)==0))
				ejem.setFechaColeccion(fechaColeccion);
						
			if(nomCien!=null && !"".equals(nomCien))
				ejem.setNombreCientifico(nomCien);
			
			if(formaIngreso!=null && !"".equals(formaIngreso))
            	ejem.setFormaIngreso(formaIngreso);
			
			
//			//asignacion de atributos al objeto tipo Ejemplar
			ejem.setNombreComun(nomComun);
			ejem.setElevacionMinima(elevacionMin);
			ejem.setElevacionMaxima(elevacionMax);
			ejem.setGradosLatitud(gradsLat);
			ejem.setMinutosLatitud(minLat);
			ejem.setSegundosLatitud(segLat);
			ejem.setGradosLatitud(gradsLat);
			ejem.setMinutosLongitud(minLon);				
			ejem.setSegundosLongitud(segLon);				
            ejem.setPublicarCoordenadas(publicarCoor);			
            ejem.setColorFlor(colFlor);            	
            ejem.setColorFruto(colFruto);
            ejem.setNombreInstitucion(nomInstitucion);
            ejem.setDisponible(disponible);
		}
		else
		{
			throw new ExcepcionLogicaNegocio("El ejemplar que intenta actualizar no existe");
		}
		
		ejemplardao.actualizar(ejem);	//actualiza la informacion del objeto de tipo Ejemplar
	}

	@Override
	public void registrarEjemplar(String especie, String municipio,
			String admin, String nomAutor, Date fechaDet,
			String nombreDeterminador, String nomColectorPpal, int numColeccion,
			Date fechaColeccion, String nomComun, String nomCien,
			int elevacionMin, int elevacionMax, int gradsLat, int minLat,
			int segLat, int gradsLon, int minLon, int segLon,
			boolean publicarCoor, String colFlor, String colFruto,
			String formaIngreso, String nomInstitucion)
			throws Excepcion, ExcepcionLogicaNegocio 
	{
		//comprueba si las datos obligatorios se ingresaron correctamente
		boolean valido = comprobarDatosObligatorios(especie, municipio, admin, nomAutor, fechaDet, nombreDeterminador, 
				nomColectorPpal, numColeccion, fechaColeccion, nomCien, publicarCoor, formaIngreso);
		
		//comprueba la existencia de la especie
		Especie specie = especiedao.obtenerEspeciePorNombre(especie);
		if(specie == null)
			valido = false;	//si la especie no existe se asume que los datos ingresados no son correctos
		
		//comprueba la existencia del municipio
		Municipio municpio = municipiodao.obtenerMunicipioPorNombre(municipio);
		if(municpio ==null)
			valido = false;	//si el municipio no existe asume que los datos ingresados no son correctos
		
		Administrador responsableRegistro = null;
		
		try	//captura un posible error por ingresar un String que no corresponda al formato de una cedula
		{
			responsableRegistro = administradordao.obtener(Integer.parseInt(admin));
			if(responsableRegistro == null)
			{
				valido = false;	//si el valor ingresado como cedula no es correcto notifica del error
				throw new ExcepcionLogicaNegocio("El administrador asignado a un ejemplar debe ser"
						+ " incorporado con su cedula (PK)");
			}
		}
		catch(NumberFormatException e)
		{
			valido = false;
			throw new ExcepcionLogicaNegocio("El administrador asignado a un ejemplar debe ser incorporado "
					+ "con su cedula (PK)");
		}
		
		if(valido)	//verifica si los datos ingresados son correctos
		{
			Ejemplar ejem = new Ejemplar();
			
			//asigna los datos que relacionan el ejemplar con otros objetos (claves foraneas)
			ejem.setEspecie(specie);
			ejem.setMunicipio(municpio);
			ejem.setResponsableRegistro(responsableRegistro);
			
			//debido a que el ejemplar es nuevo en la tabla Ejemplar, se asigna como valor de disponibilidad 
			//verdadero (es decir que no se ha eliminado)
			ejem.setDisponible(true);

			//asignacion de atributos
			ejem.setNombreAutor(nomAutor);
			ejem.setFechaDeterminacion(fechaDet);
			ejem.setNombreDeterminador(nombreDeterminador);
			ejem.setNombreColectorPrincipal(nomColectorPpal);
			ejem.setNumeroColeccion(numColeccion);
			ejem.setFechaColeccion(fechaColeccion);
			ejem.setNombreCientifico(nomCien);
			ejem.setPublicarCoordenadas(publicarCoor);
			ejem.setFormaIngreso(formaIngreso);
			
			ejem.setNombreComun(nomComun);
			ejem.setElevacionMinima(elevacionMin);
			ejem.setElevacionMaxima(elevacionMax);
			ejem.setGradosLatitud(gradsLat);
			ejem.setMinutosLatitud(minLat);
			ejem.setSegundosLatitud(segLat);
			ejem.setGradosLatitud(gradsLat);
			ejem.setMinutosLongitud(minLon);				
			ejem.setSegundosLongitud(segLon);				
            ejem.setPublicarCoordenadas(publicarCoor);			
            ejem.setColorFlor(colFlor);            	
            ejem.setColorFruto(colFruto);
            ejem.setNombreInstitucion(nomInstitucion);
            
            ejemplardao.crear(ejem);	//registra el ejemplar en la tabla Ejemplar
		}
		else
		{
			throw new ExcepcionLogicaNegocio("Algun campo fue diligenciado de manera incorrecta en el momento "
					+ "del registro del ejemplar");
		}
		
	}

	@Override
	public void eliminarEjemplar(int cod) throws Excepcion, ExcepcionLogicaNegocio 
	{
		//obtiene el ejemplar asociado al codigo ingresado
		Ejemplar ejemplar = this.ejemplardao.obtener(cod);
		if(ejemplar != null)	//verifica si fue hallado el ejemplar en la tabla Ejemplar
		{
			ejemplardao.eliminar(ejemplar);	//si se encontro se modifica su disponibilidad
		}
		else
		{
			throw new ExcepcionLogicaNegocio("El ejemplar no existe en BD, por tanto no puede eliminarse");
		}
	}
	
	/**
	 * Metodo que comprueba si las datos obligatorios pasados como parametros se ingresaron correctamente
	 * 
	 * @param especie corresponde al nombre de la especie a la que pertenece el ejemplar
	 * @param municipio hace referencia al nombre del municipio en el que se hallo el ejemplar
	 * @param admin es el nombre del usuario administrador que registro el ejemplar
	 * @param nomAutor indica el nombre de la persona que define la especie
	 * @param fechaDet es la fecha en la que se define la taxonomia del ejemplar
	 * @param nombreDeterminador hace referencia al nombre de la persona que define la taxonomia del ejemplar
	 * @param nomColectorPpal es el nombre de la persona que hallo el ejemplar
	 * @param numColeccion es el consecutivo asignado al ejemplar por su colector
	 * @param fechaColeccion indica la fecha en la que se recolecto el ejemplar
	 * @param nomCien corresponde al  nombre cientifico dado al ejemplar, combinacion de genero + especie
	 * @param publicarCoor indica si la ubicacion del ejemplar puede ser publicada o no 
	 * @param formaIngreso especifica si el ejemplar ingreso al herbario por donacion o por recoleccion
	 * 
	 * @return retorna verdadero si los datos son correctamente ingresados, falso en caso contrario
	 * 
	 * @throws Excepcion
	 * @throws ExcepcionLogicaNegocio
	 */
	
	private boolean comprobarDatosObligatorios(String especie, String municipio,
			String admin, String nomAutor, Date fechaDet,
			String nombreDeterminador, String nomColectorPpal, int numColeccion,
			Date fechaColeccion, String nomCien, boolean publicarCoor, 
			String formaIngreso) throws Excepcion, ExcepcionLogicaNegocio 
	{
		boolean datosValidos = true;	//inicializacion de la variable que almacenara el valor de retorno
				
		//Comprueba la existencia de los datos pasados como parametro en las tablas correspondientes
		Especie espec = especiedao.obtenerEspeciePorNombre(especie);	
		if(espec == null)
		{
			datosValidos = false;
			throw new ExcepcionLogicaNegocio("La especie especificada no existe");			
		}
		
		Municipio mun = municipiodao.obtenerMunicipioPorNombre(municipio);	//se comprueba si se encuentra la especie en BD
		if(mun == null)
		{
			datosValidos = false;
			throw new ExcepcionLogicaNegocio("El municipio especificado no existe");			
		}
		
		try	//captura un posible error por ingresar un String que no corresponda al formato de una cedula
		{
			if(admin!=null && "".equals(admin));
			{
				Administrador admininstrador = administradordao.obtener(Integer.parseInt(admin));
				if(admininstrador == null)
				{
					datosValidos = false;
					throw new ExcepcionLogicaNegocio("El administrador asociado no existe");
				}
			}
		}
		catch(NumberFormatException e)
		{
			datosValidos = false;
			throw new ExcepcionLogicaNegocio("El administrador asignado a un ejemplar debe ser incorporado "
					+ "con su cedula (PK)");
		}
		
		//valida si los parametros ingresados son no nulos y no vacios
		if(nomAutor==null || "".equals(nomAutor))	
			datosValidos = false;
		
		GregorianCalendar fechaActual = new GregorianCalendar();	//creo un calendar con la fecha actual
		GregorianCalendar fechaDato = new GregorianCalendar();	//creo un calendar con la fecha de nacimiento asignada
		fechaDato.setTime(fechaDet);
					
		if(fechaDet == null || !(fechaActual.after(fechaDato) || fechaActual.compareTo(fechaDato)==0))
			datosValidos = false;
		
		if(nombreDeterminador==null || "".equals(nombreDeterminador))
			datosValidos = false;
		
		if(nomColectorPpal==null || "".equals(nomColectorPpal))
			datosValidos = false;
		
		if(numColeccion <= 0)
			datosValidos = false;
		
		
		fechaDato.setTime(fechaColeccion);
		if(fechaColeccion == null || !(fechaActual.after(fechaDato) || fechaActual.compareTo(fechaDato)==0))
			datosValidos = false;
					
		if(nomCien==null || "".equals(nomCien))
			datosValidos = false;
		
		if(formaIngreso==null || "".equals(formaIngreso))
			datosValidos = false;
        	
		
		return datosValidos;	//retorna verdadero si los datos fueron ingresados correctamente, falso 
								//en caso contrario
	}
	
}
